import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
import java.util.logging.Level;

import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

public final class SecurityFuzzer {
	
	public static final int MILLIS_PER_SECOND = 1000;
	
	public static String startingPage;
	public static long timeGap;
	public static boolean pageDiscovery;
	public static boolean pageGuess;
	public static boolean passwordGuess;
	public static boolean isSensitive;

	public static boolean completeness;
	public static boolean authentication;
	public static String userName;
	public static String password;

	public static Set<String> discoverPageSet = new HashSet<String>();
	public static Set<String> queryStrings = new HashSet<String>();
	public static Set<String> sensitiveData = new HashSet<String>();
	public static final WebClient webClient = new WebClient();
	
	private SecurityFuzzer() {
	}
	
	/**
	 * @param args
	 * @throws IOException 
	 * @throws MalformedURLException 
	 * @throws FailingHttpStatusCodeException 
	 */
	public static void main(String[] args) {
		
		SecurityLoggers.setupLoggers();
		customizeFuzzer();
		discoverPageSet.add(startingPage);
		 
		try {
			HtmlPage rootPage = webClient.getPage(startingPage);
			
			if (pageDiscovery == true) {
				InputDiscovery.discoverPages(rootPage);
			}
			
			if (pageGuess == true) {
				InputDiscovery.guessPages();
			}
			
			Set<String> pageSet = Completeness.getPageCompletenessSet();
			Iterator<String> it = pageSet.iterator();
			while (it.hasNext()) {
				
				String currentURL = it.next();
				FuzzInput.tryCommonURLQueries(currentURL);
				InputDiscovery.findFormInputs(currentURL);

			}
		} catch (Exception e) {
			SecurityLoggers.errorLogger.log(Level.SEVERE, "Exception thrown in main loop", e);
		}

	}

	private static void customizeFuzzer() {
		
		Scanner scanner = new Scanner( System.in );
		
		System.out.println("What is the page we are fuzzing?");
		startingPage = scanner.next();
		
		System.out.println("Provide Authentication (True|False)");
		authentication = Boolean.parseBoolean(scanner.next());
		
		if (authentication == true) {
			System.out.print("Enter username: ");
			userName = scanner.next();
			System.out.print("Enter password: ");
			password = scanner.next();
		}
		
		System.out.println("Password guess (True|False)");
		passwordGuess = Boolean.parseBoolean(scanner.next());
		
		System.out.println("Completeness (True|False)");
		completeness = Boolean.parseBoolean(scanner.next());
		
		System.out.println("Page Guessing (True|False)");
		pageGuess = Boolean.parseBoolean(scanner.next());
		
		System.out.println("Page Discovery (True|False)");
		pageDiscovery = Boolean.parseBoolean(scanner.next());
		
		System.out.println("Sensitive data (True|False)");
		isSensitive = Boolean.parseBoolean((scanner.next()));
		if(isSensitive){
			System.out.println("Please enter the sensitive information in comma separated fromat \n" +
					"for example: admin,test123");
			String[] sensitive = scanner.next().split(",");
			for(String value: sensitive){
				sensitiveData.add(value);
			}
		}
		
		System.out.println("Input Time Gap (seconds)");
		timeGap = Long.parseLong(scanner.next());
		
		System.out.println();
		
	}
	
	public static void requestWait() {
		
		if (timeGap > 0) {
			try {
				Thread.sleep(timeGap * MILLIS_PER_SECOND);
			} catch (InterruptedException e) {
				SecurityLoggers.errorLogger.log(Level.SEVERE, "Request Wait Exception", e);
			}
		}
		
	}

}
